using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml.Linq;
using System.IO.Ports;
using System.IO;
using Microsoft.Win32;
using System.Reflection.PortableExecutable;
using System.Windows.Markup;
using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Reflection.Metadata;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    /// 


    public class SerialConfig : INotifyPropertyChanged
    {
        public ObservableCollection<string> PortNames { get; } = new ObservableCollection<string>();
        public ObservableCollection<int> BaudRates { get; } = new ObservableCollection<int>
            { 9600, 14400, 19200, 38400, 56000, 115200, 230400 };

        public ObservableCollection<Parity> ParityOptions { get; } = new ObservableCollection<Parity>
            { Parity.None, Parity.Odd, Parity.Even };

        public ObservableCollection<int> DataBitsOptions { get; } = new ObservableCollection<int>
            { 5, 6, 7, 8 };

        public ObservableCollection<StopBits> StopBitsOptions { get; } = new ObservableCollection<StopBits>
            { StopBits.None,StopBits.One, StopBits.OnePointFive, StopBits.Two };

        private string _selectedPort = "COM1";
        public string SelectedPort
        {
            get => _selectedPort;
            set => SetField(ref _selectedPort, value);
        }

        private int _selectedBaudRate = 115200;
        public int SelectedBaudRate
        {
            get => _selectedBaudRate;
            set => SetField(ref _selectedBaudRate, value);
        }

        private Parity _selectedParity = Parity.None;
        public Parity SelectedParity
        {
            get => _selectedParity;
            set => SetField(ref _selectedParity, value);
        }

        private int _selectedDataBits = 8;
        public int SelectedDataBits
        {
            get => _selectedDataBits;
            set => SetField(ref _selectedDataBits, value);
        }

        private StopBits _selectedStopBits = StopBits.One;
        public StopBits SelectedStopBits
        {
            get => _selectedStopBits;
            set => SetField(ref _selectedStopBits, value);
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string name) =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));

        protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            OnPropertyChanged(propertyName);
            return true;
        }
    }




    public partial class MainWindow : Window
    {
        
        public SerialConfig SerialConfig { get; } = new SerialConfig();
        // 添加成员变量
        private SerialPort _serialPort;
        private long _fileSizeBytes;
        private int _totalBytesReceived;
        private StringBuilder _hexDataBuilder = new StringBuilder();
        private CheckBox HEX_CheckBox;
        private readonly StringBuilder _receiveBuffer = new StringBuilder();
        private readonly object _fileLock = new object();
        private FileStream _fileStream;
        private readonly StringBuilder _dataBuffer = new StringBuilder();
        private const int BufferFlushSize = 1024; // 缓冲区刷新阈值
        private readonly object _receiveBufferLock = new object();
        private int _sendHexMode;
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;
            LoadAvailablePorts();
            // 确保保存目录存在
            EnsureDirectoryExists(txtSavePath.Text);

            //txtSavePath.Text = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SerialData.txt");
        }

        //接收区文件保存路径
        private void SaveRecvPath(object sender, RoutedEventArgs e)
        {
            var saveFileDialog = new SaveFileDialog();
            saveFileDialog.Filter = "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*";
            saveFileDialog.FileName = "hex_data.txt";
            saveFileDialog.InitialDirectory = System.IO.Path.GetDirectoryName(txtSavePath.Text);

            if (saveFileDialog.ShowDialog() == true)
            {
                txtSavePath.Text = saveFileDialog.FileName;
                EnsureDirectoryExists(txtSavePath.Text);
            }
        }

        private void 保存接收_Checked(object sender, RoutedEventArgs e)
        {
            
            try
            {
                自动保存.IsEnabled = false;
                string filePath = txtSavePath.Text;
                EnsureDirectoryExists(filePath);

                File.WriteAllText(filePath, _hexDataBuilder.ToString());

                _fileSizeBytes = new FileInfo(filePath).Length;
                lblFileSize.Content = $"{_fileSizeBytes / 1024.0:F1} KB";
            }
            catch (Exception ex)
            {
                自动保存.IsEnabled = true;
                MessageBox.Show($"保存文件失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
        private void 保存接收_Unchecked(object sender, RoutedEventArgs e)
        {
            自动保存.IsEnabled = true;
        }

            private void EnsureDirectoryExists(string filePath)
        {
            string directory = System.IO.Path.GetDirectoryName(filePath);
            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }
        }

        /*
        // 添加窗口关闭事件处理,关闭窗口时同时关闭串口
        protected override void OnClosing(CancelEventArgs e)
        {
            _serialPort?.Close();
            base.OnClosing(e);
        }
        */


        private Encoding _serialEncoding = Encoding.UTF8;
        //串口初始化
        private void InitializeSerialPort()
        {
            _serialPort = new SerialPort(
            SerialConfig.SelectedPort,
            SerialConfig.SelectedBaudRate,
            (System.IO.Ports.Parity)SerialConfig.SelectedParity,
            SerialConfig.SelectedDataBits,
            (System.IO.Ports.StopBits)SerialConfig.SelectedStopBits)
            {
                ReadBufferSize = 4096,
                //ReceivedBytesThreshold = 1,
                Encoding = _serialEncoding
            };

            _serialPort.DataReceived += SerialPort_DataReceived;
        }

        /// <summary>
        /// ////////////////////////////////////////////////////////////////
        /// </summary>
        
        // 在类中定义HEX显示标志
        private bool _hexDisplayMode = false;

        // 在UI事件中更新标志（如复选框事件）
        private void ChkHexDisplay_Checked(object sender, RoutedEventArgs e)
        {
            _hexDisplayMode = true;
        }

        private void ChkHexDisplay_Unchecked(object sender, RoutedEventArgs e)
        {
            _hexDisplayMode = false;
        }

        private void ChkHexSend_Unchecked(object sender, RoutedEventArgs e)
        {

        }

        private void ChkHexSend_Checked(object sender, RoutedEventArgs e)
        {
            _sendHexMode = 1;
        }

        // 刷新缓冲区到文件
        private void FlushBufferToFile()
        {
            if (_dataBuffer.Length == 0 || _fileStream == null) return;

            byte[] dataBytes = Encoding.UTF8.GetBytes(_dataBuffer.ToString());
            _fileStream.Write(dataBytes, 0, dataBytes.Length);
            _fileStream.Flush(); // 立即写入磁盘
            _dataBuffer.Clear();
        }

        // 修改后的数据处理方法
        private void ProcessReceivedData()
        {
            StringBuilder hexBuilder = new StringBuilder();
            while (_receiveBuffer.ToString().Contains("\n"))
            {
                string package = _receiveBuffer.ToString().Substring(0, _receiveBuffer.ToString().IndexOf("\n") + 1);
                _receiveBuffer.Remove(0, package.Length);

                // 核心修改：添加HEX转换逻辑
                string displayContent;
                string timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
                if (_hexDisplayMode)
                {
                    // 将字符串转换为字节数组
                    byte[] bytes = Encoding.UTF8.GetBytes(package);

                    // 转换为HEX格式字符串
                    displayContent = BitConverter.ToString(bytes).Replace("-", " ")+ "\r\n";
                    timestamp = DateTime.Now.ToString("HH:mm:ss.fff");
                }
                else
                {
                    displayContent = package;
                    
                }
                // 保存到缓冲区
                _hexDataBuilder.Append(displayContent);
                _totalBytesReceived += displayContent.Length;

                // 保存数据到缓冲区
                lock (_fileLock)
                {
                    _dataBuffer.Append(displayContent);

                    // 达到阈值时刷新到文件
                    if (_dataBuffer.Length >= BufferFlushSize)
                    {
                        FlushBufferToFile();
                    }
                }

                // 解决线程安全问题
                if (Dispatcher.CheckAccess())
                {
                    recv_windows.Items.Add($"[{timestamp}] 接收: {displayContent}\n");
                    recv_windows.ScrollIntoView(recv_windows.Items[recv_windows.Items.Count - 1]);
                    recv_text_windows.AppendText(timestamp);
                    recv_text_windows.AppendText(displayContent);
                    recv_text_windows.ScrollToEnd();
                    lblByteCount.Content = $"{_totalBytesReceived} 字节";
                }
                else
                {
                    Dispatcher.Invoke(() => {
                        recv_windows.Items.Add($"[{timestamp}] 接收: {displayContent}\n");
                        recv_windows.ScrollIntoView(recv_windows.Items[recv_windows.Items.Count - 1]);
                        recv_text_windows.AppendText(timestamp);
                        recv_text_windows.AppendText(displayContent);
                        recv_text_windows.ScrollToEnd();
                        lblByteCount.Content = $"{_totalBytesReceived} 字节";
                    });
                }
            }
        }
        // 在串口接收事件中调用（确保线程安全）
        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {

            // 读取数据到_receiveBuffer（需要确保线程安全）
            lock (_receiveBufferLock)
            {
                int bytesToRead = _serialPort.BytesToRead;
                byte[] buffer = new byte[bytesToRead];
                _serialPort.Read(buffer, 0, bytesToRead);
                _receiveBuffer.Append(Encoding.UTF8.GetString(buffer));
            }

            // 处理接收到的数据
            ProcessReceivedData();
        }

        /// <summary>
        /// //////////////////////////////////////////////////////////////////
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoadAvailablePorts()
        {
            try
            {
                SerialConfig.PortNames.Clear();
                foreach (var port in SerialPort.GetPortNames())
                {
                    SerialConfig.PortNames.Add(port);
                }

                if (SerialConfig.PortNames.Count > 0)
                    SerialConfig.SelectedPort = SerialConfig.PortNames[0];
            }
            catch (Exception ex)
            {
                MessageBox.Show($"加载串口失败: {ex.Message}", "错误",
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // 统一参数变更处理
        private void SerialParameter_Changed(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 0) return;

            Debug.WriteLine($"Parameter changed: {((ComboBox)sender).Name} - {e.AddedItems[0]}");
            // 这里可以添加实际的串口配置更新逻辑
        }

        private void ButtonAddName_Click(object sender, RoutedEventArgs e)
        {
            /*
            if (!string.IsNullOrWhiteSpace(txtName.Text))
            {
                recv_windows.Items.Clear();
                recv_windows.Items.Add(txtName.Text);
                
                txtName.Clear();
            }
            */
        }

        private void serialport_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
        }

        private void 校验位_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
        private void 数据位_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void 停止位_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }

        private void UpdateSerialPortStatus(bool isOpen)
        {
            串口开关.Content = isOpen ? "关闭串口" : "打开串口";
            ledStatus.Fill = isOpen ? Brushes.Green : Brushes.Gray;

            cbPort.IsEnabled = !isOpen;
            数据位.IsEnabled = !isOpen;
            校验位.IsEnabled = !isOpen;
            停止位.IsEnabled = !isOpen;
            cbBaudRate.IsEnabled = !isOpen;

            recv_windows.Items.Add($"[状态] {DateTime.Now:HH:mm:ss} 串口{(isOpen ? "已打开" : "已关闭")}");
        }

        private void UpdateUI(string message)
        {
            Dispatcher.Invoke(() =>
            {
                recv_windows.Items.Add(message);
                recv_windows.ScrollIntoView(recv_windows.Items[recv_windows.Items.Count - 1]);
            });
        }

        private void serial_onoff_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (_serialPort == null)
                {
                    InitializeSerialPort();
                    _serialPort.Open();
                    UpdateSerialPortStatus(true);
                    
                }
                else
                {
                    _serialPort.DataReceived -= SerialPort_DataReceived;
                    _serialPort.Close();
                    _serialPort = null;
                    UpdateSerialPortStatus(false);

                    lock (_fileLock)
                    {
                        if (_dataBuffer.Length > 0)
                        {
                            FlushBufferToFile();
                        }

                        _fileStream?.Close();
                        _fileStream = null;
                    }
                }
            }
            catch (IOException ex)
            {
                MessageBox.Show($"I/O错误: {ex.Message}");
            }
            catch (UnauthorizedAccessException ex)
            {
                MessageBox.Show($"无权限访问串口: {ex.Message}");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"操作失败: {ex.Message}");
            }
        }

        //刷新串口列表
        private void RefreshPorts_Click(object sender, RoutedEventArgs e)
        {
            if (_serialPort == null || !_serialPort.IsOpen)
            {
                LoadAvailablePorts();
                recv_windows.Items.Add($"[操作] {DateTime.Now:HH:mm:ss} 已刷新串口列表");
            }
            else
            {
                MessageBox.Show("请先关闭串口再刷新");
            }
        }

        // 添加编码选择功能（可选）
        private void Encoding_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (e.AddedItems.Count == 0) return;

            var selected = (ComboBoxItem)e.AddedItems[0];
            switch (selected.Content.ToString())
            {
                case "UTF-8":
                    _serialEncoding = Encoding.UTF8;
                    break;
                case "ASCII":
                    _serialEncoding = Encoding.ASCII;
                    break;
                case "GB2312":
                    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
                    _serialEncoding = Encoding.GetEncoding("GB2312");
                    break;
            }

            if (_serialPort != null && _serialPort.IsOpen)
            {
                _serialPort.Encoding = _serialEncoding;
            }
        }

        private void ClearReceData(object sender, RoutedEventArgs e)
        {
            recv_text_windows.Document.Blocks.Clear();
        }

        private void ClearSendData(object sender, RoutedEventArgs e)
        {
            send_windows.Clear();
        }

        private void 自动保存_Checked(object sender, RoutedEventArgs e)
        {
            SaveReceCheckBox.IsEnabled = false;
            if (自动保存.IsChecked == true)
            {
                // 初始化文件流
                _fileStream = new FileStream(
                    txtSavePath.Text,
                    FileMode.Append,
                    FileAccess.Write,
                    FileShare.Read
                );
            }
            
        }

        private void 自动保存_Unchecked(object sender, RoutedEventArgs e)
        {
            SaveReceCheckBox.IsEnabled = true;
            lock (_fileLock)
            {
                if (_dataBuffer.Length > 0)
                {
                    FlushBufferToFile();
                }

                _fileStream?.Close();
                _fileStream = null;
            }
        }

        private void SendData(object sender, RoutedEventArgs e)
        {
            try
            {
                if (chkHexSend.IsChecked == true)
                {
                    // 将文本转换为字节数组（根据你的协议可能需要修改编码）
                    byte[] data = Encoding.UTF8.GetBytes(send_windows.Text);

                    // 发送数据
                    _serialPort.Write(data, 0, data.Length);
                }
                else
                {
                    string data = send_windows.Text.ToString();
                    _serialPort.WriteLine(data);
                }
                
            }
            catch (Exception ex)
            {
                MessageBox.Show($"发送失败: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}
